package com.mytrip.service.impl;

import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import com.mytrip.base.service.impl.BaseManagerImpl;
import com.mytrip.dao.CityDAO;
import com.mytrip.dao.TripDAO;
import com.mytrip.dao.TripNotifyUserDAO;
import com.mytrip.dao.TripPlanDAO;
import com.mytrip.dao.TripPlanFlightDAO;
import com.mytrip.dao.TripPlanHotelDAO;
import com.mytrip.dao.TripPlanMeetingDAO;
import com.mytrip.dao.TripPlanNoteDAO;
import com.mytrip.model.City;
import com.mytrip.model.CityExample;
import com.mytrip.model.Trip;
import com.mytrip.model.TripExample;
import com.mytrip.model.TripNotifyUser;
import com.mytrip.model.TripNotifyUserExample;
import com.mytrip.model.TripPlan;
import com.mytrip.model.TripPlanExample;
import com.mytrip.model.TripPlanFlight;
import com.mytrip.model.TripPlanFlightExample;
import com.mytrip.model.TripPlanHotel;
import com.mytrip.model.TripPlanHotelExample;
import com.mytrip.model.TripPlanMeeting;
import com.mytrip.model.TripPlanMeetingExample;
import com.mytrip.model.TripPlanNote;
import com.mytrip.model.TripPlanNoteExample;
import com.mytrip.service.TripManager;
import com.mytrip.util.Constant;
import com.mytrip.util.HttpUtil;
import com.mytrip.webapp.filter.CtxSessionBag;

public class TripManagerImpl extends BaseManagerImpl implements TripManager{

	private TripDAO tripDAO;

	private TripNotifyUserDAO tripNotifyUserDAO;

	private TripPlanDAO tripPlanDAO;

	private TripPlanFlightDAO tripPlanFlightDAO;

	private TripPlanHotelDAO tripPlanHotelDAO;

	private TripPlanMeetingDAO tripPlanMeetingDAO;

	private TripPlanNoteDAO tripPlanNoteDAO;

	private CityDAO cityDAO;

	public void setCityDAO(CityDAO cityDAO){
		this.cityDAO = cityDAO;
	}

	public void setTripDAO(TripDAO tripDAO){
		this.tripDAO = tripDAO;
	}

	public void setTripNotifyUserDAO(TripNotifyUserDAO tripNotifyUserDAO){
		this.tripNotifyUserDAO = tripNotifyUserDAO;
	}

	public void setTripPlanDAO(TripPlanDAO tripPlanDAO){
		this.tripPlanDAO = tripPlanDAO;
	}

	public void setTripPlanFlightDAO(TripPlanFlightDAO tripPlanFlightDAO){
		this.tripPlanFlightDAO = tripPlanFlightDAO;
	}

	public void setTripPlanHotelDAO(TripPlanHotelDAO tripPlanHotelDAO){
		this.tripPlanHotelDAO = tripPlanHotelDAO;
	}

	public void setTripPlanMeetingDAO(TripPlanMeetingDAO tripPlanMeetingDAO){
		this.tripPlanMeetingDAO = tripPlanMeetingDAO;
	}

	public void setTripPlanNoteDAO(TripPlanNoteDAO tripPlanNoteDAO){
		this.tripPlanNoteDAO = tripPlanNoteDAO;
	}

	@Override
	public List<City> queryAllCity(){
		CityExample example = new CityExample();
		example.setOrderByClause("province asc,name asc");
		return cityDAO.selectByExample(example);
	}

	@Override
	public Integer addTrip(Trip trip){
		Integer uid = CtxSessionBag.getSessionBag().getUserinfo().getId();
		trip.setUid(uid);

		String name = trip.getName();
		if (name == null || "".equals(name)) {
			String fromCityName = cityDAO.selectByPrimaryKey(trip.getFromCity()).getName();
			String toCityName = cityDAO.selectByPrimaryKey(trip.getToCity()).getName();
			trip.setName(fromCityName + " - " + toCityName);
		}

		Calendar endDateCal = Calendar.getInstance();
		endDateCal.setTime(trip.getEndDate());
		endDateCal.set(Calendar.HOUR_OF_DAY, 23);
		endDateCal.set(Calendar.MINUTE, 59);
		endDateCal.set(Calendar.SECOND, 59);
		trip.setEndDate(endDateCal.getTime());

		trip.setTripStatus(Trip.STATUS_DRAFT);
		return tripDAO.insert(trip);
	}

	@Override
	public void saveTripNotifyUser(TripNotifyUser tripNotifyUser){
		tripNotifyUserDAO.insert(tripNotifyUser);
	}

	@Override
	public List<Trip> queryHistoryTrip(int from, int size){
		Integer uid = CtxSessionBag.getSessionBag().getUserinfo().getId();
		TripExample example = new TripExample();
		example.setOrderByClause("end_date desc limit " + from + "," + size);
		example.createCriteria().andUidEqualTo(uid).andEndDateLessThan(new Date()).andTripStatusEqualTo(
				Trip.STATUS_FINISH);
		return tripDAO.selectByExample(example);
	}

	@Override
	public List<Trip> queryNextTrip(int from, int size){
		Integer uid = CtxSessionBag.getSessionBag().getUserinfo().getId();
		TripExample example = new TripExample();
		example.setOrderByClause("start_date asc limit " + from + "," + size);
		example.createCriteria().andUidEqualTo(uid).andEndDateGreaterThanOrEqualTo(new Date()).andTripStatusEqualTo(
				Trip.STATUS_FINISH);
		return tripDAO.selectByExample(example);
	}

	@Override
	public List<Trip> queryDraftTrip(int from, int size){
		Integer uid = CtxSessionBag.getSessionBag().getUserinfo().getId();
		TripExample example = new TripExample();
		example.setOrderByClause("start_date asc limit " + from + "," + size);
		example.createCriteria().andUidEqualTo(uid).andTripStatusEqualTo(Trip.STATUS_DRAFT);
		return tripDAO.selectByExample(example);
	}

	@Override
	public Trip queryTripById(int id){
		return tripDAO.selectByPrimaryKey(id);
	}

	@Override
	public void editTrip(Trip trip){
		Integer uid = CtxSessionBag.getSessionBag().getUserinfo().getId();

		Trip old = this.queryTripById(trip.getId());
		if (old == null || !uid.equals(old.getUid())) {
			log.warn("old == null || !uid.equals(old.getId()) , " + uid);
			return;
		}

		String name = trip.getName();
		if (name == null || "".equals(name)) {
			String fromCityName = cityDAO.selectByPrimaryKey(trip.getFromCity()).getName();
			String toCityName = cityDAO.selectByPrimaryKey(trip.getToCity()).getName();
			old.setName(fromCityName + " - " + toCityName);
		} else {
			old.setName(name);
		}

		old.setIsTraveler(trip.getIsTraveler());
		old.setIsPublic(trip.getIsPublic());
		old.setFromCity(trip.getFromCity());
		old.setToCity(trip.getToCity());
		old.setTripStatus(Trip.STATUS_DRAFT);
		old.setPhoto(trip.getPhoto());
		old.setEndDate(trip.getEndDate());

		tripDAO.updateByPrimaryKeySelective(old);
	}

	@Override
	public void clearTripNotifyUserByTripId(Integer id){
		TripNotifyUserExample example = new TripNotifyUserExample();
		example.createCriteria().andTidEqualTo(id);
		tripNotifyUserDAO.deleteByExample(example);
	}

	@Override
	public City queryCityById(Integer id){
		return cityDAO.selectByPrimaryKey(id);
	}

	@Override
	public int queryDraftTripCnt(){
		Integer uid = CtxSessionBag.getSessionBag().getUserinfo().getId();
		TripExample example = new TripExample();
		example.createCriteria().andUidEqualTo(uid).andTripStatusEqualTo(Trip.STATUS_DRAFT);
		return tripDAO.countByExample(example);
	}

	@Override
	public int queryHistoryTripCnt(){
		Integer uid = CtxSessionBag.getSessionBag().getUserinfo().getId();
		TripExample example = new TripExample();
		example.createCriteria().andUidEqualTo(uid).andEndDateLessThan(new Date()).andTripStatusEqualTo(
				Trip.STATUS_FINISH);
		return tripDAO.countByExample(example);
	}

	@Override
	public int queryNextTripCnt(){
		Integer uid = CtxSessionBag.getSessionBag().getUserinfo().getId();
		TripExample example = new TripExample();
		example.createCriteria().andUidEqualTo(uid).andEndDateGreaterThanOrEqualTo(new Date()).andTripStatusEqualTo(
				Trip.STATUS_FINISH);
		return tripDAO.countByExample(example);
	}

	@Override
	public void deleteTrip(Trip trip){
		trip.setTripStatus(Trip.STATUS_DELETE);
		tripDAO.updateByPrimaryKeySelective(trip);
	}

	@Override
	public void finishTrip(Trip trip){
		trip.setTripStatus(Trip.STATUS_FINISH);
		tripDAO.updateByPrimaryKeySelective(trip);
	}

	@Override
	public List<TripPlan> queryTripPlanByTrip(Integer tripId){
		TripPlanExample example = new TripPlanExample();
		example.createCriteria().andTidEqualTo(tripId);
		List<TripPlan> planList = tripPlanDAO.selectByExample(example);

		for (TripPlan plan : planList) {
			if (TripPlan.TYPE_FLIGHT.equals(plan.getType())) {
				TripPlanFlightExample e = new TripPlanFlightExample();
				e.createCriteria().andPidEqualTo(plan.getId());
				plan.setFlight(tripPlanFlightDAO.selectByExample(e).get(0));
			} else if (TripPlan.TYPE_HOTEL.equals(plan.getType())) {
				TripPlanHotelExample e = new TripPlanHotelExample();
				e.createCriteria().andPidEqualTo(plan.getId());
				plan.setHotel(tripPlanHotelDAO.selectByExample(e).get(0));
			} else if (TripPlan.TYPE_MEETING.equals(plan.getType())) {
				TripPlanMeetingExample e = new TripPlanMeetingExample();
				e.createCriteria().andPidEqualTo(plan.getId());
				plan.setMeeting(tripPlanMeetingDAO.selectByExample(e).get(0));
			} else if (TripPlan.TYPE_NOTE.equals(plan.getType())) {
				TripPlanNoteExample e = new TripPlanNoteExample();
				e.createCriteria().andPidEqualTo(plan.getId());
				plan.setNote(tripPlanNoteDAO.selectByExample(e).get(0));
			}
		}

		return planList;
	}

	@Override
	public List<TripNotifyUser> queryNotifyUserByTrip(Integer tripId){
		TripNotifyUserExample example = new TripNotifyUserExample();
		example.setOrderByClause("id asc");
		example.createCriteria().andTidEqualTo(tripId);
		return tripNotifyUserDAO.selectByExample(example);
	}

	@Override
	public Integer addPlan(TripPlan plan){
		plan.setNotifyStatus(TripPlan.NOTIFY_STATUS_INIT);
		Integer pid = tripPlanDAO.insert(plan);

		String type = plan.getType();
		if (TripPlan.TYPE_FLIGHT.equals(type)) {
			TripPlanFlight flight = plan.getFlight();
			flight.setPid(pid);
			tripPlanFlightDAO.insert(flight);
		} else if (TripPlan.TYPE_HOTEL.equals(type)) {
			TripPlanHotel hotel = plan.getHotel();
			hotel.setPid(pid);
			tripPlanHotelDAO.insert(hotel);
		} else if (TripPlan.TYPE_MEETING.equals(type)) {
			TripPlanMeeting meeting = plan.getMeeting();
			meeting.setPid(pid);
			tripPlanMeetingDAO.insert(meeting);
		} else if (TripPlan.TYPE_NOTE.equals(type)) {
			TripPlanNote note = plan.getNote();
			note.setPid(pid);
			tripPlanNoteDAO.insert(note);
		} else {
			throw new RuntimeException("type is illegal");
		}

		return pid;
	}

	@Override
	public List<City> queryTripCitys(){
		List<City> cityList = null;
		Integer uid = CtxSessionBag.getSessionBag().getUserinfo().getId();
		TripExample tripExample = new TripExample();
		tripExample.createCriteria().andUidEqualTo(uid).andTripStatusEqualTo(Trip.STATUS_FINISH);
		List<Trip> tripList = tripDAO.selectByExample(tripExample);

		List<Integer> cityIdList = new LinkedList<Integer>();
		for (Trip trip : tripList) {
			Integer toCity = trip.getToCity();
			if (toCity != null && !cityIdList.contains(toCity)) {
				cityIdList.add(toCity);
			}
		}

		if (cityIdList != null && cityIdList.size() != 0) {
			CityExample cityExample = new CityExample();
			cityExample.createCriteria().andIdIn(cityIdList);
			cityList = cityDAO.selectByExample(cityExample);
		} else {
			cityList = Collections.EMPTY_LIST;
		}

		return cityList;
	}

	@Override
	public List<Trip> queryAllFinishedTrip(){
		Integer uid = CtxSessionBag.getSessionBag().getUserinfo().getId();
		TripExample example = new TripExample();
		example.createCriteria().andUidEqualTo(uid).andTripStatusEqualTo(Trip.STATUS_FINISH);
		return tripDAO.selectByExample(example);
	}

	@Override
	public TripPlan queryPlanById(Integer pid){
		return tripPlanDAO.selectByPrimaryKey(pid);
	}

	@Override
	public void deletePlan(TripPlan plan){
		Integer pid = plan.getId();
		String type = plan.getType();
		if (TripPlan.TYPE_FLIGHT.equals(type)) {
			TripPlanFlightExample example = new TripPlanFlightExample();
			example.createCriteria().andPidEqualTo(pid);
			tripPlanFlightDAO.deleteByExample(example);
		} else if (TripPlan.TYPE_HOTEL.equals(type)) {
			TripPlanHotelExample example = new TripPlanHotelExample();
			example.createCriteria().andPidEqualTo(pid);
			tripPlanHotelDAO.deleteByExample(example);
		} else if (TripPlan.TYPE_MEETING.equals(type)) {
			TripPlanMeetingExample example = new TripPlanMeetingExample();
			example.createCriteria().andPidEqualTo(pid);
			tripPlanMeetingDAO.deleteByExample(example);
		} else if (TripPlan.TYPE_NOTE.equals(type)) {
			TripPlanNoteExample example = new TripPlanNoteExample();
			example.createCriteria().andPidEqualTo(pid);
			tripPlanNoteDAO.deleteByExample(example);
		} else {
			throw new RuntimeException("type is illegal");
		}

		tripPlanDAO.deleteByPrimaryKey(pid);
	}

	@Override
	public String queryCityWeather(Integer cityId){
		String thinkpageKey = Constant.getCommonConf("thinkpageKey");
		String cityWeatherId = this.queryCityById(cityId).getWeatherId();
		String res = HttpUtil.get("http://www.thinkpage.cn/weather/api.svc/getWeather?city=" + cityWeatherId
				+ "&language=zh-chs&provider=cma&unit=c&key=" + thinkpageKey);
		return res;
	}

	@Override
	public void notifyPlan(TripPlan plan, Boolean ckd){
		plan.setNotifyStatus(ckd ? TripPlan.NOTIFY_STATUS_WAIT : TripPlan.NOTIFY_STATUS_INIT);
		tripPlanDAO.updateByPrimaryKeySelective(plan);
	}

}
